package com.msun.auth.apiAdmin.handler;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.msun.auth.apiAdmin.AdminContext;
import com.msun.auth.custom.annotation.ContextWithToken;
import com.msun.auth.custom.annotation.ResponseResult;
import com.msun.auth.custom.comdto.DataBox;
import com.msun.auth.custom.comdto.PageListDto;
import com.msun.auth.custom.constants.CustomConsts;
import com.msun.auth.custom.constants.RoleLevels;
import com.msun.auth.custom.exception.BizException;
import com.msun.auth.custom.exception.BizResultCode;
import com.msun.auth.database.model.*;
import com.msun.auth.utils.CheckUtils;
import com.msun.auth.utils.JwtUtils;
import com.msun.auth.utils.SysOaUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 类描述：
 *
 * @ClassName UserManager
 * @Description TODO
 * @Author gj
 * @Date 2023/8/19 12:56
 * @Version 1.0
 */
@Api(tags = "用户管理")
@ResponseResult
@RestController
@RequestMapping("/admin/user/")
public class UserManager {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AppMapper appMapper;
    @Autowired
    private AppUserMapper appUserMapper;
    @Autowired
    private GroupMapper groupMapper;
    @Autowired
    private GroupRoleMapper groupRoleMapper;
    @Autowired
    private GroupUserMapper groupUserMapper;

    @Data
    public static class ImportUserFromOaArgs {
        @NotBlank
        private String uname;
        @NotBlank
        private String passwd;
    }

    @ApiOperation("登录页面-导入OA用户")
    @ApiResponses({@ApiResponse(code = 200, message = "成功", response = DataBox.class)})
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("importUserFromOa")
    public DataBox importUserFromOa(@RequestBody @Valid ImportUserFromOaArgs args) {
        SysOaUtils.UserInfo ui = SysOaUtils.syncUser(args.getUname());
        if (ui == null) {
            throw new BizException(BizResultCode.AccountNotExist, "您的用户名不存在OA系统中，请联系OA运营平台负责人");
        }
        if (new LambdaQueryChainWrapper<>(userMapper)
                .eq(UserMo::getId, ui.getId())
                .exists()) {
            throw new BizException(BizResultCode.Error, StrUtil.format("用户【{}】已被导入到系统", args.getUname()));
        }
        UserMo user = new UserMo();
        user.setId(ui.getId());
        user.setUname(args.getUname());
        user.setPasswd(args.getPasswd());
        user.setName(ui.getName());
        user.setSex(ui.getSex());
        user.setSexName(ui.getSexName());
        user.setJobTitle(ui.getJobTitle());
        user.setMobile(ui.getMobile());
        user.setEmail(ui.getEmail());
        user.setRoleLevel(RoleLevels.READ);
        user.setCreateTime(new Date());
        userMapper.insert(user);
        return DataBox.of(true);
    }

    @Data
    public static class AdminLoginArgs {
        @NotBlank
        private String uname;
        @NotBlank
        private String passwd;
        private Long groupId;
        private Long appId;
    }

    @Data
    public static class AdminLoginDto {
        private String token;
        private Long uid;
        private String uname;
        private String name;
        private Long appId;
        private Long groupId;
        private String showTitle;
        private Integer roleLevel;
    }

    @ApiOperation("管理员登录")
    @ApiResponses({@ApiResponse(code = 200, message = "成功", response = AdminLoginDto.class)})
    @PostMapping("adminLogin")
    public AdminLoginDto adminLogin(@RequestBody @Valid AdminLoginArgs args) {
        UserMo user = new LambdaQueryChainWrapper<>(userMapper)
                .eq(UserMo::getUname, args.getUname())
                .one();
        if (user == null) {
            throw new BizException(BizResultCode.AccountNotExist);
        }
        AdminLoginDto dto = new AdminLoginDto();
        Map<String, Object> tokenInfo = new HashMap<>();
        tokenInfo.put(CustomConsts.UID, String.valueOf(user.getId()));
        tokenInfo.put(CustomConsts.UNAME, user.getUname());
        tokenInfo.put(CustomConsts.NAME, user.getName());
        if (CheckUtils.notZero(args.getAppId())) {
            AppMo app = new LambdaQueryChainWrapper<>(appMapper)
                    .eq(AppMo::getId, args.getAppId())
                    .one();
            if (app == null) {
                throw new BizException(BizResultCode.RecordNotExist, "无效应用");
            }
            AppUserMo appUser = new LambdaQueryChainWrapper<>(appUserMapper)
                    .eq(AppUserMo::getAppId, args.getAppId())
                    .eq(AppUserMo::getUid, user.getId())
                    .one();
            if (appUser == null) {
                throw new BizException(BizResultCode.Error, "您不是该项目成员");
            }
            GroupRoleMo groupRole = new LambdaQueryChainWrapper<>(groupRoleMapper)
                    .eq(GroupRoleMo::getId, appUser.getGroupRoleId())
                    .one();
            if (groupRole.getRoleLevel() < RoleLevels.APP_ADMIN) {
                throw new BizException(BizResultCode.NoRight);
            }
            dto.setRoleLevel(RoleLevels.APP_ADMIN);
            dto.setAppId(app.getId());
            dto.setShowTitle(app.getAppName());
            dto.setGroupId(app.getGroupId());
            tokenInfo.put(CustomConsts.ROLE_LEVEL, String.valueOf(RoleLevels.APP_ADMIN));
            tokenInfo.put(CustomConsts.APP_ID, String.valueOf(app.getId()));
            tokenInfo.put(CustomConsts.GROUP_ID, String.valueOf(app.getGroupId()));
        } else if (CheckUtils.notZero(args.getGroupId())) {
            GroupMo group = new LambdaQueryChainWrapper<>(groupMapper)
                    .eq(GroupMo::getId, args.getGroupId())
                    .one();
            if (group == null) {
                throw new BizException(BizResultCode.RecordNotExist, "无效项目组");
            }
            GroupUserMo groupUser = new LambdaQueryChainWrapper<>(groupUserMapper)
                    .eq(GroupUserMo::getGroupId, group.getId())
                    .eq(GroupUserMo::getUid, user.getId())
                    .one();
            if (groupUser == null) {
                throw new BizException(BizResultCode.RecordNotExist, "您不是该小组成员");
            }
            GroupRoleMo groupRole = new LambdaQueryChainWrapper<>(groupRoleMapper)
                    .eq(GroupRoleMo::getId, groupUser.getGroupRoleId())
                    .one();
            if (groupRole.getRoleLevel() < RoleLevels.GROUP_ADMIN) {
                throw new BizException(BizResultCode.NoRight);
            }
            dto.setRoleLevel(RoleLevels.GROUP_ADMIN);
            dto.setGroupId(group.getId());
            dto.setShowTitle(group.getGroupName());
            tokenInfo.put(CustomConsts.ROLE_LEVEL, String.valueOf(RoleLevels.GROUP_ADMIN));
            tokenInfo.put(CustomConsts.GROUP_ID, String.valueOf(group.getId()));
        } else {
            if (user.getRoleLevel() < RoleLevels.SUPER_ADMIN) {
                throw new BizException(BizResultCode.NoRight);
            }
            dto.setRoleLevel(RoleLevels.SUPER_ADMIN);
            dto.setShowTitle("统一认证平台");
            tokenInfo.put(CustomConsts.ROLE_LEVEL, String.valueOf(RoleLevels.SUPER_ADMIN));
        }
        String token = JwtUtils.createToken(tokenInfo, CustomConsts.SIGN_KEY, user.getUname(), 86400000L);
        dto.setToken(token);
        dto.setUid(user.getId());
        dto.setUname(user.getUname());
        dto.setName(user.getName());
        dto.setRoleLevel(user.getRoleLevel());
        return dto;
    }

    @Data
    public static class AppLoginArgs {
        @NotBlank
        private String uname;
        @NotBlank
        private String passwd;
        @NotNull
        private Long appId;
    }

    @Data
    public static class AppLoginDto {
        private String token;
        private Long uid;
        private String uname;
        private String name;
        private Long groupId;
        private Long appId;
        private String frontIp;
        private Integer frontPort;
        private String activeRole;
    }

    @ApiOperation("应用登录")
    @ApiResponses({@ApiResponse(code = 200, message = "成功", response = AppLoginDto.class)})
    @PostMapping("appLogin")
    public AppLoginDto appLogin(@RequestBody @Valid AppLoginArgs args) {
        UserMo user = new LambdaQueryChainWrapper<>(userMapper)
                .eq(UserMo::getUname, args.getUname())
                .one();
        if (user == null) {
            throw new BizException(BizResultCode.AccountNotExist, "请先导入OA用户，然后联系项目管理员将您添加为项目成员");
        }
        AppMo app = new LambdaQueryChainWrapper<>(appMapper)
                .eq(AppMo::getId, args.getAppId())
                .one();
        if (app == null) {
            throw new BizException(BizResultCode.AccountNotExist, "该应用不存在");
        }
        AppUserMo appUser = new LambdaQueryChainWrapper<>(appUserMapper)
                .eq(AppUserMo::getUid, user.getId())
                .eq(AppUserMo::getAppId, args.getAppId())
                .one();
        if (appUser == null) {
            throw new BizException(BizResultCode.NoRight, "请通知项目管理员将您添加到项目成员中");
        }
        Map<String, Object> tokenInfo = new HashMap<>();
        tokenInfo.put(CustomConsts.APP_ID, String.valueOf(app.getId()));
        tokenInfo.put(CustomConsts.UID, String.valueOf(user.getId()));
        tokenInfo.put(CustomConsts.UNAME, user.getUname());
        tokenInfo.put(CustomConsts.NAME, user.getName());
        tokenInfo.put(CustomConsts.GROUP_ID, String.valueOf(app.getGroupId()));
        GroupRoleMo groupRole = new LambdaQueryChainWrapper<>(groupRoleMapper)
                .eq(GroupRoleMo::getGroupId, appUser.getGroupRoleId())
                .one();
        tokenInfo.put(CustomConsts.ROLE_LEVEL, groupRole.getRoleLevel());
        String token = JwtUtils.createToken(tokenInfo, CustomConsts.SIGN_KEY, user.getUname(), 86400000L);
        AppLoginDto dto = new AppLoginDto();
        dto.setToken(token);
        dto.setUid(user.getId());
        dto.setUname(user.getUname());
        dto.setName(user.getName());
        dto.setGroupId(app.getGroupId());
        dto.setAppId(app.getId());
        dto.setFrontIp(app.getFrontIp());
        dto.setFrontPort(app.getFrontPort());
        dto.setActiveRole(app.getActiveRule());
        return dto;
    }


    //获取所有用户列表
    @Data
    public static class GetAllUserListArgs {
        private Integer pageNo;
        private Integer pageSize;
        private String keyword;
    }

    @ApiOperation("超级管理员-获取所有用户列表")
    @ApiResponses({@ApiResponse(code = 200, message = "成功", response = UserMo.class)})
    @ContextWithToken
    @PostMapping("superAdminGetAllUserList")
    public PageListDto<UserMo> superAdminGetAllUserList(@RequestBody GetAllUserListArgs args) {
        AdminContext.Context ctx = AdminContext.get();
        if (ctx.getRoleLevel() < RoleLevels.SUPER_ADMIN) {
            throw new BizException(BizResultCode.NoRight);
        }
        if (CheckUtils.isZero(args.getPageNo())) {
            args.setPageNo(1);
        }
        if (CheckUtils.isZero(args.getPageSize())) {
            args.setPageSize(20);
        }
        Page<UserMo> page = new LambdaQueryChainWrapper<>(userMapper)
                .gt(UserMo::getId, 0)
                .and(StrUtil.isNotBlank(args.getKeyword()), (i) -> i.like(UserMo::getUname, args.getKeyword()).or().like(UserMo::getName, args.getKeyword()))
                .orderByAsc(UserMo::getId)
                .page(new Page<>(args.getPageNo(), args.getPageSize(), true));

        PageListDto<UserMo> dto = new PageListDto<>();
        dto.setArr(page.getRecords());
        dto.setPageNo(args.getPageNo());
        dto.setPageSize(args.getPageSize());
        dto.setTotal(page.getTotal());
        return dto;
    }

    @Data
    public static class DelUserArgs {
        private Long uid;
    }

    @ApiOperation("超级管理员-删除用户")
    @ApiResponses({@ApiResponse(code = 200, message = "成功", response = DataBox.class)})
    @Transactional(rollbackFor = Exception.class)
    @ContextWithToken
    @PostMapping("superAdminDelUser")
    public DataBox superAdminDelUser(@RequestBody DelUserArgs args) {
        AdminContext.Context ctx = AdminContext.get();
        if (ctx.getRoleLevel() < RoleLevels.SUPER_ADMIN) {
            throw new BizException(BizResultCode.NoRight);
        }
        if (new LambdaQueryChainWrapper<>(groupUserMapper)
                .eq(GroupUserMo::getUid, args.getUid())
                .exists()) {
            throw new BizException(BizResultCode.Error, "请先将该用户从所有小组中删除");
        }
        userMapper.deleteById(args.getUid());
        return DataBox.of(true);
    }
}